#!/usr/bin/env python
# -*- coding: utf-8 -*-

from peewee import OperationalError
from peewee import __exception_wrapper__,InterfaceError,MySQLDatabase
from .my_log import logger
from conf import conf
import traceback
import pymysql
pymysql.install_as_MySQLdb()


sa = conf.sqlalchemy
_mysql = conf.mysql

class RetryOperationalError(object):
    def execute_sql(self, sql, params=None, commit=True):
        try:
            cursor = super(RetryOperationalError, self).execute_sql(
                sql, params, commit)
        except InterfaceError:
            try:
                logger.error(traceback.format_exc())
                self.connect(reuse_if_open=True)
                cursor = super(RetryOperationalError, self).execute_sql(
                        sql, params, commit)
            except OperationalError:
                logger.error(traceback.format_exc())
                if not self.is_closed():
                    self.close()
                with __exception_wrapper__:
                    cursor = self.cursor()
                    cursor.execute(sql, params or ())
                    if commit and not self.in_transaction():
                        self.commit()
        except OperationalError:
            logger.error(traceback.format_exc())
            if not self.is_closed():
                self.close()
            with __exception_wrapper__:
                cursor = self.cursor()
                cursor.execute(sql, params or ())
                if commit and not self.in_transaction():
                    self.commit()
        return cursor

class RetryMySQLDatabase(RetryOperationalError, MySQLDatabase):
    pass


database = RetryMySQLDatabase(**_mysql)

class Base(object):
    __table_args__ = {
        'mysql_charset': 'utf8mb4'
    }

    @property
    def columns(self):
        return [c.name for c in self.__table__.columns]

    @property
    def columnitems(self):
        return dict([(c, getattr(self, c)) for c in self.columns])

    @property
    def dict(self):
        return {c.name: getattr(self, c.name, None) for c in self.__table__.columns}

    def __repr__(self):
        return '{}({})'.format(self.__class__.__name__, self.columnitems)

    def tojson(self):
        return self.columnitems


from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

db_engine = create_engine(f"mysql+mysqlconnector://{_mysql.user}:{_mysql.password}@{_mysql.host}/{_mysql.database}?charset={_mysql.charset}",
                          echo=sa.echo,
                          pool_size=sa.pool_size,
                          pool_recycle=sa.pool_recycle)
SessionFactory = sessionmaker(bind=db_engine,
                              autoflush=sa.autoflush)
